package com.apobates.forum.toro.tuple;

import com.apobates.forum.toro.core.BeanParser;
import com.apobates.forum.toro.core.Corner;
import com.apobates.forum.toro.core.Express;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

/**
 * 单一左对象Triple映射语句
 * @param <L> 左对象类型
 * @since 20220827
 * @author xiaofanku@live.cn
 */
public class TripleMapperStatements<L> {
    private final static BeanParser<TripleMapperStatements.Argument> parser;
    static {
        // M(middleAttr:middleAttrType)#R(rightAttr:rightAttrType)
        Express exp = Express.getInstance()
                .word("middleAttr")
                .corner(Corner.sequence(0).edge(":").build())
                .word("middleAttrType")
                .corner(Corner.sequence(1).edge(")#R(").build())
                .word("rightAttr")
                .corner(Corner.sequence(2).edge(":").build())
                .word("rightAttrType")
                .corner(Corner.sequence(3).edge(")").build());
        // 从表达式到实例
        parser = exp.build(TripleMapperStatements.Argument.class);
    }
    /**
     * 设置连接M的属性名称。避免与expr并用
     * @param middleAttr 左对象关联的属性名
     * @return
     */
    public Argument middle(String middleAttr) {
        return new Argument().middle(middleAttr);
    }

    /**
     * 设置参数语句表达式描述
     * 通过描述字符串设置右对象的连接属性。注意：不要与attr混用
     * 格式: M(middleAttr:middleAttrType)#R(rightAttr:rightAttrType)
     * @param exprDescribe 查询参数表达式描述
     * @return
     */
    public Argument expr(String exprDescribe) {
        Map<String,Object> argMap = parser.toMap(exprDescribe, "M(");
        return new Argument()
                .middle(argMap.get("middleAttr").toString())
                .middleType(argMap.get("middleAttrType").toString())
                .right(argMap.get("rightAttr").toString())
                .rightType(argMap.get("rightAttrType").toString());
    }
    /**
     * ASF Lang3 Triple连接参数
     */
    public class Argument{
        // L中哪个属性连接M
        private String middleAttr;
        private String middleAttrType;
        // L中哪个属性连接R
        private String rightAttr;
        private String rightAttrType;

        private Argument() {

        }
        /**
         * 设置连接M的属性名称
         * @param middleAttr 连接M的属性名称
         * @return
         */
        public Argument middle(String middleAttr){
            this.middleAttr = middleAttr;
            return this;
        }

        /**
         * 设置连接M的属性类型
         * @param middleAttrType 关联的属性类型
         * @return
         */
        public Argument middleType(String middleAttrType){
            this.middleAttrType = middleAttrType;
            return this;
        }

        /**
         * 设置连接R的属性名称
         * @param rightAttr 右对象关联的属性名称
         * @return
         */
        public Argument right(String rightAttr){
            this.rightAttr = rightAttr;
            return this;
        }

        /**
         * 设置连接R的属性类型
         * @param rightAttrType 右对象关联的属性类型
         * @return
         */
        public Argument rightType(String rightAttrType) {
            this.rightAttrType = rightAttrType;
            return this;
        }
        /**
         * 左对象与中右对象是一对一
         * @param leftIns
         * @return
         */
        public TripleMapperExecutor<L> by(L leftIns){
            return new TripleMapperExecutor(()->leftIns, this.buildArguments());
        }

        /**
         * 左对象与中右对象是一对一
         * @param leftInsSup
         * @return
         */
        public TripleMapperExecutor<L> supply(Supplier<L> leftInsSup){
            return new TripleMapperExecutor(leftInsSup, this.buildArguments());
        }

        private Map<String,String> buildArguments(){
            Map<String, String> arguments = new HashMap<>();
            arguments.put("middleAttr", this.middleAttr);
            arguments.put("middleAttrType", this.middleAttrType);
            arguments.put("rightAttr", this.rightAttr);
            arguments.put("rightAttrType", this.rightAttrType);
            return arguments;
        }

    }
}
